﻿#region Namespace
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using DCT.CodeBox.EventTrigger.Codes;
using System.Collections.Concurrent;
#endregion

namespace DCT.CodeBox.TaskManager.Codes
{
    public abstract class TaskDispatcher
    {
        #region 事件定义
        private EventTrigger<TaskDispatcherStatusChangedEventArg> statusChangedTrigger =
            EventTrigger<TaskDispatcherStatusChangedEventArg>.CreateInstance();
        private EventTrigger<TaskItemWrapperEventArg> itemAddedTrigger =
            EventTrigger<TaskItemWrapperEventArg>.CreateInstance();
        private EventTrigger<TaskItemEventArg> itemRemovedTrigger =
            EventTrigger<TaskItemEventArg>.CreateInstance();
        private EventTrigger<TaskItemWithExceptionEventArg> itemExecuteCompletedTrigger =
            EventTrigger<TaskItemWithExceptionEventArg>.CreateInstance();

        public EventTriggerListener<TaskDispatcherStatusChangedEventArg> EventStatusChanged
        {
            get { return this.statusChangedTrigger.OutsideListener; }
        }
        public EventTriggerListener<TaskItemWrapperEventArg> EventItemAdded
        {
            get { return this.itemAddedTrigger.OutsideListener; }
        }
        public EventTriggerListener<TaskItemEventArg> EventItemRemoved
        {
            get { return this.itemRemovedTrigger.OutsideListener; }
        }
        public EventTriggerListener<TaskItemWithExceptionEventArg> EventItemExecuteCompleted
        {
            get { return this.itemExecuteCompletedTrigger.OutsideListener; }
        }
        #endregion

        #region 构造函数、初始化
        public TaskDispatcher()
        {
            this.Status = TaskDispatcherStatus.Idle;
        }
        #endregion

        #region 状态操作相关

        public virtual void Start()
        {
            StatusChange(TaskDispatcherStatus.StartActive);
        }

        public virtual void Resume()
        {
            StatusChange(TaskDispatcherStatus.ResumeActive);
        }

        public virtual void Stop()
        {
            StatusChange(TaskDispatcherStatus.Idle);
        }

        public virtual void Pause()
        {
            StatusChange(TaskDispatcherStatus.Pause);
        }

        private volatile TaskDispatcherStatus status = default(TaskDispatcherStatus);

        public virtual TaskDispatcherStatus Status { get { return status; } protected set { status = value; } }

        public bool IsActive {
            get
            {
                return this.status == TaskDispatcherStatus.StartActive || this.status == TaskDispatcherStatus.ResumeActive;
            }
        }

        private void StatusChange(TaskDispatcherStatus target)
        {
            if (this.Status != target)
            {
                this.statusChangedTrigger.Fire(new TaskDispatcherStatusChangedEventArg(this
                    , this.Status
                    , target));
                this.Status = target;
            }
        }
        #endregion

        #region 运行TaskItem相关
        protected abstract bool ValidExecuteTaskItem(object config);

        /// <summary>
        /// 执行TaskItem
        /// </summary>
        /// <param name="wrapper"></param>
        /// <returns>true，继续下一个TaskItem；false，中断执行</returns>
        protected virtual bool ExecuteTaskItem(TaskItemWrapper wrapper)
        {
            bool continueExecute = false;

            //执行前，就先检查一下状态，如果是非活动，就停止
            if (!this.IsActive)
            {
                return continueExecute;
            }

            if (this.ValidExecuteTaskItem(wrapper.Config))  //判断是否执行具体任务
            {
                Exception exception = null;
                try
                {
                    wrapper.TaskItem.Execute(wrapper.Arg);
                }
                catch (Exception ex)
                {
                    exception = ex;
                }
                finally
                {
                    this.itemExecuteCompletedTrigger.Fire(new TaskItemWithExceptionEventArg(this
                        , wrapper.TaskItem
                        , exception));
                }
            }

            continueExecute = true;   //继续下一个TaskItem
            return continueExecute;
        }
        #endregion

        #region 管理TaskItem相关
        protected List<TaskItemWrapper> wrappers = new List<TaskItemWrapper>();
        protected object lockWrapper = new object();

        public virtual void AddTaskItemRange(List<TaskItemWrapper> tasks)
        {
            if (tasks == null || tasks.Count == 0)
            {
                return;
            }
            lock (lockWrapper)
            {
                wrappers.AddRange(tasks);
            }
            //多次触发事件
            foreach (var task in tasks)
            {
                this.itemAddedTrigger.Fire(new TaskItemWrapperEventArg(this, task));
            }
        }

        public virtual void AddTaskItem(ITaskItem taskItem, object arg, object config)
        {
            TaskItemWrapper wrapper = new TaskItemWrapper(taskItem, arg, config);
            lock (lockWrapper)
            {
                wrappers.Add(wrapper);
            }
            this.itemAddedTrigger.Fire(new TaskItemWrapperEventArg(this, wrapper));
        }

        public virtual bool RemoveTaskItem(ITaskItem taskItem)
        {
            bool remove = false;
            TaskItemWrapper find = wrappers.Find(delegate(TaskItemWrapper _wrapper)
            {
                return _wrapper.TaskItem == taskItem;
            });
            if (find != null)
            {
                lock (lockWrapper)
                {
                    remove = wrappers.Remove(find);
                }
            }
            return remove;
        }

        public virtual ReadOnlyCollection<ITaskItem> TaskItems
        {
            get
            {
                return this.wrappers.ConvertAll<ITaskItem>(delegate(TaskItemWrapper _item)
                {
                    return _item.TaskItem;
                }).AsReadOnly();
            }
        }
        #endregion
    }
}
